#include "Application.h"
#include "Source.h"
#include <QDebug>

namespace MessagingMenu
{

Application::Application(QObject *parent) : QObject(parent), m_app(0)
{
    connect(this, &Application::desktopIdChanged, this, &Application::initApplication);
}

Application::Application(QObject *parent, const QString &desktopId):
    QObject(parent), m_app(0)
{
    connect(this, &Application::desktopIdChanged, this, &Application::initApplication);
    set_desktopId(desktopId);
}

void Application::sourceActivated(MessagingMenuApp *, const gchar *id, gpointer appPtr)
{
    qDebug() << "SOURCE ACTIVATED";
    Application *app = reinterpret_cast<Application *>(appPtr);
    const bool notNull = app != NULL;
    qDebug() << "app is not null: " << notNull;
    QString sourceId(id);
    qDebug() << "Emitting source activated";
    app->emitSourceActivated(sourceId);
}

void Application::shiftPositions(const int &position, const int shift)
{
    if (position >= 0) {
        for (auto it = m_sources.begin(); it != m_sources.end(); ++it) {
            if ((*it)->position() >= position) {
                (*it)->setPosition((*it)->position() + shift);
            }
        }
    }
}
// This function does not add the source to the messaging menu. You need to call Source::create() on the returned object
Source *Application::createMessageSource(const QString sourceId, const QString &sourceLabel, const QString &icon, bool persistent, qint32 position)
{
    shiftPositions(position);
    QUrl iconUrl = QUrl::fromLocalFile(icon);
    if (!iconUrl.isLocalFile()) {
        // TODO: set a default url
    }
    Source *source = new Source(this, sourceId, sourceLabel, iconUrl);
    source->setPersistent(persistent);
    int pos = position >= 0 ? position : m_sources.size() - 1;
    source->setPosition(pos);
    return source;
}

void Application::removeSource(const Source &source)
{
    if (hasSource(source)) {
        messaging_menu_app_remove_source(m_app, source.id().toUtf8().data());
        int pos = source.position();
        m_sources.remove(source.id());
        shiftPositions(pos, -1);
    }
}

bool Application::hasSource(const Source &source)
{
    return messaging_menu_app_has_source(m_app, source.id().toUtf8().data());
}

MessagingMenuApp *Application::getApp() const
{
    return m_app;
}

void Application::initApplication()
{
    if (!checkDesktopIdExists()) {
        return;
    }
    const gchar * desktopId = m_desktopId.toUtf8().data();
    m_app = messaging_menu_app_new(desktopId);
    Q_ASSERT(m_app);
    g_signal_connect(m_app, "activate-source", G_CALLBACK(Application::sourceActivated), this);
}

void Application::emitSourceActivated(const QString &id)
{
    Q_EMIT msgSourceActivated(id);
}

void Application::registerApplication()
{
    if (!checkDesktopIdExists()) {
        return;
    }
    if (m_app == NULL) {
        initApplication();
    }
    messaging_menu_app_register(m_app);
}

void Application::unregisterApplication()
{
    if (!checkDesktopIdExists()) {
        return;
    }
    if (m_app == NULL) {
        initApplication();
    }
    messaging_menu_app_unregister(m_app);
}

bool Application::checkDesktopIdExists()
{
    if (m_desktopId.isEmpty()) {
        Q_EMIT error(Error::NO_DESKTOP_ID);
        set_errorString(errorToString(Error::NO_DESKTOP_ID));
        return false;
    }
    return true;
}

}
